﻿using Aspose.Pdf;
using Aspose.Pdf.Generator;
using Aspose.Pdf.Text;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;

namespace WindowsPdfToImg
{
    public partial class qyx : Form
    {
        public qyx()
        {

            InitializeComponent();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 选择文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //创建文件弹出选择窗口（包括文件名）对象
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "选择文件";
            ofd.Multiselect = true;
            ofd.Filter = "(*.pdf)|*.pdf";//设置文件过滤类型

            //清空选择文件的文本框内容 和执行结果的文本框内容
            this.files.Text = "";
            this.result.Text = "";
            this.errorMsg.Text = "";

            //判断选择的路径
            if (ofd.ShowDialog() == DialogResult.OK)
            {

                foreach (var item in ofd.FileNames)
                {
                    this.files.Text += item + "\r\n";
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 默认选中第一个单选框
            img_radio.Checked = true;

            this.files.AllowDrop = true;

            
        }

        /// <summary>
        /// 选择保存目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void selectDirectory_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.RootFolder = System.Environment.SpecialFolder.Desktop;
            fbd.ShowNewFolderButton = true;
            fbd.Description = "选择目录";

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                this.directory.Text = fbd.SelectedPath.ToString();
            }

        }

        private void label1_Click_1(object sender, EventArgs e)
        {

        }

        private void files_TextChanged(object sender, EventArgs e)
        {

        }

        private void files_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void files_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            foreach (string file in files)
            {
                if (Path.GetExtension(file) == ".pdf")  //判断文件类型，只接受txt文件
                {
                    this.files.Text += file + "\r\n";
                }
            }
        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 提交
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void submit_Click(object sender, EventArgs e)
        {
            var file = this.files.Text;


            result.Text = "";
            errorMsg.Text = "";
            pdf_text.Text = "";

            if (string.IsNullOrEmpty(file))
            {
                MessageBox.Show("请选择要转换的Pdf文件！");
                return;
            }

            var directory = this.directory.Text;
            if (string.IsNullOrEmpty(directory))
            {
                MessageBox.Show("请设置保存目录！");
                return;
            }

            var timeRadio = this.timeRadio.Checked;
            var wordsRadio = this.wordsRadio.Checked;

            //if (!timeRadio && !wordsRadio)
            //{
            //    MessageBox.Show("请设置水印类型！");
            //    return;
            //}

            //转换图片
            var img_radio = this.img_radio.Checked;

            //转换word
            var word_radio = this.word_radio.Checked;




            this.submit.Enabled = false;
            this.btnSelect.Enabled = false;
            this.selectDirectory.Enabled = false;

            var dateTimePicker1 = this.dateTimePicker1.Value;
            var watermarkWord = this.watermarkWord.Text;

            var text = "";
            if (timeRadio)
            {
                text = dateTimePicker1.ToString();
            }
            else if (wordsRadio)
            {
                text = watermarkWord;
            }

            //转换类型 1、转图片 2、转word
            var type = 0;

            if (img_radio)
            {
                type = 1;
            }
            else if (word_radio)
            {
                type = 2;
            }


            foreach (var i in file.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries))
            {
                var m = new Files
                {
                    Path = i,
                    Text = text,
                    Directory = directory,
                    Name = "",
                    Type = type
                };

                queue.Enqueue(m);
            }

            //启动任务
            StartQueue();
        }



        private void close_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void timeRadio_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void groupBox1_Enter_1(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// pdf转换为图片
        /// </summary>
        /// <param name="file"></param>
        /// <param name="text"></param>
        /// <param name="directory"></param>
        public void CreatImg(string file, string text, string directory)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();


            var qualityText = this.resolutionText.Text;
            var quality = 80;

            var resolutionText = this.resolutionText.Text;
            var reso = 80;

            if (!string.IsNullOrEmpty(qualityText))
            {
                quality = Convert.ToInt32(qualityText);

                if (quality >= 128) { quality = 128; }
            }

            if (!string.IsNullOrEmpty(resolutionText))
            {
                reso = Convert.ToInt32(resolutionText);
            }

            Directory.CreateDirectory(directory);

            string filename = System.IO.Path.GetFileName(file);//文件名  “Default.aspx”
            string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(file);// 没有扩展名的文件名 “Default”

            //创建目录
            Directory.CreateDirectory(directory + "\\" + fileNameWithoutExtension);

            //图片输出地址
            var imageOutputDirPath = directory;

            //分辨率
            var resolution = new Aspose.Pdf.Devices.Resolution(reso);

            //初始化
            var pdf = new Aspose.Pdf.Document(file);

            //设置进度条基础信息
            var count = pdf.Pages.Count;
            this.progressBar1.Value = 0;
            this.progressBar1.Style = ProgressBarStyle.Blocks;
            this.progressBar1.Maximum = count;
            this.progressBar1.Minimum = 0;
            this.progressBar1.MarqueeAnimationSpeed = 100;
            this.progressBar1.Step = 1;
            this.lbl_progress.Text = "0%";
            this.lbl_progress.Refresh();



            this.Invoke(new Action(() =>
            {
                result.Text += $"文件{file}已经开始处理{DateTime.Now},";
            }));


            Page testpage = pdf.Pages[1];
            // 创建对象
            TextStamp textStamp = new TextStamp(text);

            // 设定原点
            textStamp.XIndent = (testpage.PageInfo.Width / 2) - 200;//(testpage.PageInfo.Width / 2)
            textStamp.YIndent = (testpage.PageInfo.Height / 2);//(testpage.PageInfo.Height / 2)

            // 设置文本属性
            textStamp.TextState.Font = FontRepository.FindFont("SimSun");
            textStamp.TextState.FontSize = 40.0F;
            textStamp.TextState.FontStyle = FontStyles.Italic;
            textStamp.TextState.ForegroundColor = Aspose.Pdf.Color.FromRgb(System.Drawing.Color.Gray);
            textStamp.Opacity = 50;

            // 设置文本水印的戳记ID，以便以后识别它
            textStamp.setStampId(123456);

            // Add stamp to particular page


            Document doc = new Document();
            Page page = doc.Pages.Add();

            try
            {
                var i = 0;
                foreach (Aspose.Pdf.Page item in pdf.Pages)
                {
                    i++;

                    this.Invoke(new Action(() =>
                    {
                        pdf_text.Text = $"正在转换文件:《{filename}》,总共{count}页,当前第{i}页,还剩余{count - i}页";
                    }));

                    var filename2 = imageOutputDirPath + "/" + fileNameWithoutExtension + "/" + i + ".jpeg";

                    // 创建Image对象，命名空间是必要的，因为在别的命名空间也有Image类
                    Aspose.Pdf.Image image = new Aspose.Pdf.Image();

                    //添加水印
                    item.AddStamp(textStamp);

                    new Aspose.Pdf.Devices.JpegDevice(resolution, quality).Process(item, filename2);

                    // 设置Image数据源
                    // 如果是本地文件或Web图片，直接设置File属性即可
                    image.File = filename2; // "http://localhost/test.jpg"

                    System.Drawing.Image srcImage = System.Drawing.Image.FromFile(filename2);
                    int h = srcImage.Height;
                    int w = srcImage.Width;

                    //var w = (int)item.PageInfo.Width;
                    //var h = (int)item.PageInfo.Height;

                    page.PageInfo.Height = (h);
                    page.PageInfo.Width = (w);
                    page.PageInfo.Margin.Bottom = (0);
                    page.PageInfo.Margin.Top = (0);
                    page.PageInfo.Margin.Right = (0);
                    page.PageInfo.Margin.Left = (0);

                    // 添加图片到页面段落
                    page.Paragraphs.Add(image);

                    //进度条
                    this.progressBar1.PerformStep();
                    //设置百分比
                    double dCount = count, dProg = this.progressBar1.Value;
                    this.lbl_progress.Text = Math.Round((dProg / dCount) * 100).ToString() + "%";
                }

                this.Invoke(new Action(() =>
                {
                    pdf_text.Text += $",新文件正在保存中...";
                }));

                var newFileName = fileNameWithoutExtension + "__已处理.pdf";
                doc.Save(imageOutputDirPath + "/" + newFileName);



                this.Invoke(new Action(() =>
                {
                    pdf_text.Text += $",新文件已经保存成功！";
                }));

                sw.Stop();
                this.Invoke(new Action(() =>
                {
                    result.Text += $"已经处理完成,总共{i}页，{DateTime.Now},耗时{Tools.RevertToTime(sw.ElapsedMilliseconds)}\r\n";
                }));

            }
            catch (Exception ex)
            {
                this.Invoke(new Action(() =>
                {
                    errorMsg.Text += $"文件{file}异常：{ex.ToString()}\r\n";
                }));

                this.submit.Enabled = true;
                this.btnSelect.Enabled = true;
                this.selectDirectory.Enabled = true;
            }




            //删除文件
            //for (int j = 1; j <= i; j++)
            //{
            //    File.Delete(imageOutputDirPath + "/" + fileNameWithoutExtension + "/"+ j + ".jpeg");
            //}


            GC.Collect();
        }

        /// <summary>
        /// 转换为word
        /// </summary>
        /// <param name="path"></param>
        /// <param name="directory"></param>
        public void CreatWordTest(string file, string directory)
        {
            //计时
            Stopwatch sw = new Stopwatch();
            sw.Start();

            //创建目录
            Directory.CreateDirectory(directory);

            string filename = System.IO.Path.GetFileName(file);//文件名  “Default.aspx”
            string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(file);// 没有扩展名的文件名 “Default”

            //创建目录
            Directory.CreateDirectory(directory + "\\" + fileNameWithoutExtension);

            //文档输出地址
            var wordOutputDirPath = directory;


            try
            {
                //初始化
                var pdf = new Aspose.Pdf.Document(file);

                //设置进度条基础信息
                var count = pdf.Pages.Count;
                this.progressBar1.Value = 0;
                this.progressBar1.Style = ProgressBarStyle.Blocks;
                this.progressBar1.Maximum = count;
                this.progressBar1.Minimum = 0;
                this.progressBar1.MarqueeAnimationSpeed = 100;
                this.progressBar1.Step = 1;
                this.lbl_progress.Text = "0%";
                this.lbl_progress.Refresh();


                this.Invoke(new Action(() =>
                {
                    result.Text += $"文件{file}已经开始处理{DateTime.Now},";
                }));


                var filename2 = wordOutputDirPath + "/" + fileNameWithoutExtension + "/" + fileNameWithoutExtension + "_已转换.docx";

                //进度条
                this.progressBar1.PerformStep();
                //设置百分比
                double dCount = count, dProg = this.progressBar1.Value;
                this.lbl_progress.Text = Math.Round((dProg / dCount) * 100).ToString() + "%";

                // 将 PDF 转换为 Word (.docx)
                pdf.Save(filename2, SaveFormat.DocX);

                this.Invoke(new Action(() =>
                {
                    pdf_text.Text += $",新文件已经保存成功！";
                }));




                sw.Stop();
                this.Invoke(new Action(() =>
                {
                    result.Text += $"已经处理完成，{DateTime.Now},耗时{Tools.RevertToTime(sw.ElapsedMilliseconds)}\r\n";
                }));
            }
            catch (Exception ex)
            {

                this.Invoke(new Action(() =>
                {
                    errorMsg.Text += $"文件{file}异常：{ex.ToString()}\r\n";
                }));

                this.submit.Enabled = true;
                this.btnSelect.Enabled = true;
                this.selectDirectory.Enabled = true;
            }


            GC.Collect();

        }


        /// <summary>
        /// 转换为word
        /// </summary>
        /// <param name="file"></param>
        /// <param name="directory"></param>
        public void CreatWord(string file, string directory)
        {
            // 计时
            Stopwatch sw = new Stopwatch();
            sw.Start();

            try
            {
                // 创建目录，只调用一次
                string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(file);
                string outputDir = Path.Combine(directory, fileNameWithoutExtension);
                Directory.CreateDirectory(outputDir);  // 只调用一次

                // 文档输出地址
                var wordOutputPath = Path.Combine(outputDir, $"{fileNameWithoutExtension}_已转换.docx");

                // 初始化 PDF
                var pdf = new Aspose.Pdf.Document(file);

                // 设置进度条基础信息
                var pageCount = pdf.Pages.Count;
                this.progressBar1.Invoke(new Action(() =>
                {
                    this.progressBar1.Value = 0;
                    this.progressBar1.Style = ProgressBarStyle.Blocks;
                    this.progressBar1.Maximum = pageCount + 100; // 增加保存过程的进度
                    this.progressBar1.Minimum = 0;
                    this.progressBar1.MarqueeAnimationSpeed = 100;
                    this.progressBar1.Step = 1;
                    this.lbl_progress.Text = "0%";
                    this.lbl_progress.Refresh();
                }));

                // 处理进度更新
                this.Invoke(new Action(() =>
                {
                    result.Text += $"文件{file}已经开始处理{DateTime.Now},";
                }));

                // 每处理100页更新一次进度
                int updateInterval = Math.Max(1, pageCount / 100);
                for (int i = 1; i <= pageCount; i++)
                {
                    // 每处理一定数量的页数更新一次进度条
                    if (i % updateInterval == 0)
                    {
                        this.progressBar1.Invoke(new Action(() =>
                        {
                            this.progressBar1.Value = i;
                            double progressPercentage = (double)i / pageCount * 100;
                            this.lbl_progress.Text = $"{Math.Round(progressPercentage)}%";
                        }));
                    }
                }

                // 模拟保存过程的进度更新
                this.progressBar1.Invoke(new Action(() =>
                {
                    this.progressBar1.Value = pageCount; // 处理完页数后，先把进度条更新到100%（页数处理完）
                }));

                // 将 PDF 转换为 Word (.docx)
                pdf.Save(wordOutputPath, SaveFormat.DocX);

                // 模拟保存过程进度
                for (int i = pageCount; i <= pageCount + 100; i++) // 增加进度条范围，模拟保存过程
                {
                    int progress = i;
                    this.progressBar1.Invoke(new Action(() =>
                    {
                        this.progressBar1.Value = progress;
                        double progressPercentage = (double)progress / (pageCount + 100) * 100;
                        this.lbl_progress.Text = $"{Math.Round(progressPercentage)}%";
                    }));

                    // 假设保存过程需要 1 秒钟，模拟进度更新
                    Thread.Sleep(10);
                }

                this.Invoke(new Action(() =>
                {
                    pdf_text.Text += $",新文件已经保存成功！";
                }));

                // 完成处理
                sw.Stop();
                this.Invoke(new Action(() =>
                {
                    result.Text += $"已经处理完成，{DateTime.Now},耗时{Tools.RevertToTime(sw.ElapsedMilliseconds)}\r\n";
                }));
            }
            catch (Exception ex)
            {
                this.Invoke(new Action(() =>
                {
                    errorMsg.Text += $"文件{file}异常：{ex.ToString()}\r\n";
                }));
            }
            finally
            {
                // 恢复 UI 状态
                this.Invoke(new Action(() =>
                {
                    submit.Enabled = true;
                    btnSelect.Enabled = true;
                    selectDirectory.Enabled = true;
                }));
            }
        }



        private void result_TextChanged(object sender, EventArgs e)
        {

        }

        #region 队列相关
        private static ConcurrentQueue<Files> queue = new ConcurrentQueue<Files>();
        private static bool hasQueue = false; //任务状态


        /// <summary>
        /// 启动队列任务
        /// </summary>
        private void StartQueue()
        {
            if (hasQueue == false)
            {

                hasQueue = true;
                System.Threading.Tasks.Task.Run(() =>
                {
                    QueueEach_Pdf();
                });
            }
        }

        /// <summary>
        /// 安全队列执行任务
        /// </summary>
        /// <param name="SourceType"></param>
        public async void QueueEach_Pdf()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();

            while (hasQueue)
            {
                if (queue.Count > 0)
                {
                    List<Files> list = new List<Files>();

                    try
                    {
                        this.Invoke(new Action(() =>
                        {
                            result.Text = $"文件处理开始,总共{queue.Count}个文件,当前时间{DateTime.Now}\r\n";
                        }));

                        var count = queue.Count;
                        for (int i = 0; i < count; i++)
                        {
                            Files item = new Files();
                            bool dequeueSuccesful = false;
                            dequeueSuccesful = queue.TryDequeue(out item);

                            if (dequeueSuccesful)
                            {
                                //判断转换类型 1、转换为图片 2、转换为word
                                if (item.Type == 1)
                                {
                                    CreatImg(item.Path, item.Text, item.Directory);
                                }
                                else if (item.Type == 2)
                                {
                                    CreatWord(item.Path,  item.Directory);
                                }


                            }
                        }

                        sw.Stop();
                        this.Invoke(new Action(() =>
                        {
                            result.Text += $"文件处理结束{DateTime.Now},耗时{Tools.RevertToTime(sw.ElapsedMilliseconds)}\r\n";
                        }));

                        this.submit.Enabled = true;
                        this.btnSelect.Enabled = true;
                        this.selectDirectory.Enabled = true;
                    }
                    catch (Exception ex)
                    {

                        this.Invoke(new Action(() =>
                        {
                            errorMsg.Text += $"队列执行异常：{ex.ToString()}\r\n";
                        }));

                        this.submit.Enabled = true;
                        this.btnSelect.Enabled = true;
                        this.selectDirectory.Enabled = true;
                    }
                }
            }
        }


        #endregion

        private void files_DockChanged(object sender, EventArgs e)
        {

        }

        private void label5_Click(object sender, EventArgs e)
        {

        }

        private void progressBar1_Click(object sender, EventArgs e)
        {

        }

        private void lbl_progress_Click(object sender, EventArgs e)
        {

        }

        private void progressBar2_Click(object sender, EventArgs e)
        {

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 控制键盘输入只能是自然数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            // 允许输入:数字、退格键(8)、全选(1)、复制(3)、粘贴(22)
            if (!Char.IsDigit(e.KeyChar) && e.KeyChar != 8 &&
          e.KeyChar != 1 && e.KeyChar != 3 && e.KeyChar != 22)
            {
                e.Handled = true;
            }
        }

        private void word_radio_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void wordsRadio_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}
